home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v9n03.arc / XALL.ASM < prev    next >
Assembly Source File  |  1990-01-12  |  21KB  |  367 lines

  1.         PAGE   60,132
  2.         TITLE  Xall - High speed eXeute in ALL subdirs utility
  3.         SUBTTL General Program description
  4. ;-----------------------------------------------------------------------------;
  5. ; Xall - eXecute any command in current directory plus all subdirectories     ;
  6. ;-----------------------------------------------------------------------------;
  7. ;    XALL 1.0 ■ PCDATA TOOLKIT Copyright (c) 1990 Ziff Communications Co.     ;
  8. ;                   PC Magazine ■ Wolfgang Stiller                            ;
  9. ;                                                                             ;
  10. ;-----------------------------------------------------------------------------;
  11. ;Purpose:                                                                     ;
  12. ; XALL will eXecute any command in the current directory plus all             ;
  13. ;      subdirectories below that one.  This program is written for high       ;
  14. ;      speed execution (lean and mean!).                                      ;
  15. ;-----------------------------------------------------------------------------;
  16. ;Syntax:                                                                      ;
  17. ;                                                                             ;
  18. ;XALL anyDOScommand                                                           ;
  19. ;                                                                             ;
  20. ;  "anyDOScommand" may be any batch file, program, or DOS command. Any        ;
  21. ;                  programs or batch files should be located in a             ;
  22. ;                  directory specified in the DOS path (PATH=).               ;
  23. ;-----------------------------------------------------------------------------;
  24. ;Remarks:                                                                     ;
  25. ;  "anyDOScommand" will be executed first in the current directory and        ;
  26. ;  then in each subdirectory subordinate to the current directory.  This      ;
  27. ;  program has been optimized for speed and efficiency of execution.  If      ;
  28. ;  execution is terminated, you will be in the directory currently being      ;
  29. ;  processed.  This program does NOT check for execution of other             ;
  30. ;  programs that change the drive or directory. (Speed is the goal!)          ;
  31. ;  XALL has advanced error recovery and provides clear explanations to        ;
  32. ;  PCDATA Toolkit user of what has gone wrong, such as an                     ;
  33. ;  invalid COMSPEC environment variable.                                      ;
  34. ;                                                                             ;
  35. ;  XALL will return the following DOS errorlevels:                            ;
  36. ;                                                                             ;
  37. ;  00 - normal completion                                                     ;
  38. ;  32 - any abnormal occurance - indicates fatal termination.                 ;
  39. ;-----------------------------------------------------------------------------;
  40.  
  41.  
  42. ;-----------------------------------------------------------------;
  43. ; Constants:                                                      ;
  44. ;-----------------------------------------------------------------;
  45. BOX                  EQU  254             ;Small box character code
  46. CR                   EQU  0Dh             ; Carriage return
  47. LF                   EQU  0Ah             ; Line feed
  48. CRLF                 EQU  0A0D            ; CR+LF in one word
  49. First_time           EQU  00h             ; Constant to indicate first time
  50. Not_First_Time       EQU  0FFh            ;             indicate NOT first time
  51. Subdirectory_attrib  EQU  10h             ; Bit pattern to find directories
  52.  
  53. CSEG    SEGMENT
  54.         ASSUME  CS:CSEG, DS:CSEG,ES:CSEG,SS:CSEG
  55.         ORG     2Ch                       ;Segment of environment found here
  56. Environment LABEL BYTE
  57.  
  58.         ORG     7DH                       ;Just before paramter area in PSP
  59. XALL_PARM LABEL  BYTE
  60.  
  61.         ORG     80h                       ;Normal DOS PSP parameter area
  62. PSP_PARM  LABEL  BYTE
  63.  
  64. ;*****************************************************************************
  65. ;** Main program begins here:  XALL - Subdirectory Command eXecuter         **
  66. ;**                            ----                                         **
  67. ;*****************************************************************************
  68.  
  69.         ORG     100h                      ;This is a .COM type program
  70. XALL:
  71.         MOV     SP,OFFSET STACK_TOP       ;Create new stack
  72.  
  73.         MOV     DX,OFFSET XALL_CR_MSG     ;Copyright message
  74.         MOV     AH,09h                    ;DOS print string function
  75.         INT     21h
  76.  
  77.         MOV     BX,offset Program_top     ;End of program + 15 (segment roundng)
  78.         MOV     CX,4                      ;Prepare to div by 4 (calc # of paras)
  79.         SHR     BX,CL                     ;Convert to segment address
  80.         MOV     AH,4Ah                    ;Release uneeded memory
  81.         INT     21h
  82.  
  83.         CALL    Get_COMSPEC               ;Locate the compsec in the environment
  84.         CALL    Create_EXEC_parm_BLOCK    ;Create parameter block for DOS EXEC
  85.         CALL    Create_Command_tail       ;Create /C command for COMMAND.COM
  86.  
  87. ;***********************;
  88. ; MAIN loop begins here ;
  89. ;***********************;
  90. EXEC_Next_Command:                        ;Come here to execute a command
  91.                                           ;in each directory
  92.         CALL    DISPLAY_XALL_MSG          ;Display msg that we are this directry
  93.  
  94. ;---------------------------------------------------------------------------;
  95. ; Use DOS EXEC function to invoke COMMAND.COM with user's specified command ;
  96. ;              tail from the parameter area at 80h.                         ;
  97.         LDS    DX,[Command_Adr]           ;DS:DX is address of command.com str
  98.         MOV    BX,OFFSET Parm_block       ;ES:BX is adr of parameter block
  99.         MOV    AX,4b00h                   ;DOS EXEC sub-task function
  100.         INT    21h                        ;COMMAND.COM now executing user's cmd
  101.  
  102. ; Return from execution of DOS shell - all registers may be corrupted:
  103.         MOV     AX,CS                     ;CS is only OK register
  104.         MOV     ES,AX
  105.         MOV     DS,AX
  106.         MOV     SS,AX
  107.         MOV     SP,OFFSET Stack_top       ;Reset stack pointer
  108.         JC      Handle_Exec_Error         ;If DOS EXEC function failed handle it
  109.  
  110. ;-----------------------------------------------------------------------------;
  111. ;   Now find NEXT (or first) subdirectory below the current one               ;
  112. ;-----------------------------------------------------------------------------;
  113. Find_another_SubDirectory:
  114.         MOV     DX,[DTA_Ptr]              ;Tell DOS to use different DTA
  115.         MOV     AH,1Ah                    ;DOS set DTA function
  116.         INT     21h
  117.  
  118.         CMP     FF_Flag,First_time        ;Is this first time in this directory?
  119.         JNE     Find_next                 ;   IF not, do a find next
  120.         MOV     DX,OFFSET Global_str      ;   Else do an initial find on *.*
  121.         MOV     CX,Subdirectory_attrib    ;       find only subdirectories
  122.         MOV     AH,4Eh                    ;       DOS FIND 1st function
  123.         INT     21h
  124.         JMP     SHORT Validate_directory  ;Skip the FIND NEXT function call
  125.  
  126. Find_Next:                                ;Find the next directory
  127.         MOV     AH,4Fh                    ;DOS find next function
  128.         INT     21h
  129.  
  130. Validate_directory:                       ;Check that we found valid directory
  131.         JC      Return_to_Mother          ;If find failed, Return to  mother dir
  132.         MOV     DI,[DTA_Ptr]              ;Get address of current DTA
  133.  
  134. ;     Check the file attribute bits in the DTA (is it a directory or a file?)
  135.         TEST    BYTE PTR [DI+21],Subdirectory_attrib  ;Is this a directory?
  136.         JE      Find_Next                 ;If its not a directory keep looking
  137.  
  138.         ADD     DI,30                     ;Point to directory name in DTA
  139.         CMP     BYTE PTR [DI],'.'         ;IS it a '.' or '..' dir entry?
  140.         JE      Find_Next                 ;   IF so, ignore it and find next dir
  141.  
  142.         ADD     [DTA_Ptr],43              ;Go down one level + use a new DTA
  143.         MOV     FF_Flag,First_time ;Set flag to do intial *.* dir find
  144.  
  145. ; Change to new daughter directory:
  146.         MOV     DX,DI                     ;point to directory to change to
  147.         MOV     AH,3Bh                    ;DOS change directory function
  148.         INT     21h
  149.  
  150.         JMP     SHORT EXEC_Next_Command   ;Go execute command in this new Dir
  151.  
  152. ;-----------------------------------------------------------------------------;
  153. ; HANDLE EXEC ERROR - Produce specific error messages for the possible DOS    ;
  154. ;                     return codes from the EXEC function which may reasonably;
  155. ;                     happen as a result of  command or configuration error.  ;
  156. ;-----------------------------------------------------------------------------;
  157. Handle_Exec_Error:                       ;Come here if, DOS EXEC func failed
  158.         CMP     AX,02                     ;= file not found/path invalid ?
  159.         JNE     Handle_Exec_A             ;   If not, check other codes
  160.         MOV     DX, OFFSET EXEC_02_Msg    ;   Else put out appropriate error msg
  161.         JMP     Error_Exit                ;   Print error message and terminate
  162. Handle_Exec_A:                            ;Keep checking other possible codes:
  163.         CMP     AX,05                     ;= Access denied return code?
  164.         JNE     Handle_Exec_B             ;   If not, check other codes
  165.         MOV     DX, OFFSET EXEC_05_Msg    ;   Else put out appropriate error msg
  166.         JMP     Error_Exit                ;   Print error message and terminate
  167. Handle_Exec_B:                            ;Keep checking other possible codes:
  168.         CMP     AX,08                     ;= Isufficient memory return code?
  169.         JNE     Unexpected_error          ;   If not, its an unexpected error..
  170.         MOV     DX, OFFSET EXEC_08_Msg    ;   Else put out appropriate error msg
  171.         JMP     Error_Exit                ;   Print error message and terminate
  172. Unexpected_error:                         ;Put out a general catchall error msg
  173.         MOV     DX,OFFSET XALL_fail_msg   ;message for unexpected errors
  174.         JMP     Error_Exit                ;   Print error message and terminate
  175.  
  176. ;-----------------------------------------------------------------------------;
  177. ; R E T U R N  T O   M O T H E R  - No more files in prior directory so we    ;
  178. ;                                   return to the previous level and find next;
  179. ;-----------------------------------------------------------------------------;
  180. Return_to_Mother:                         ;Go up one level to mother directory
  181.         CMP     [DTA_Ptr],OFFSET DTA_Area ;Are we back in original directory?
  182.         JNZ     Return_to_Prior_Dir       ;  If not, set directory back 1 level
  183.         JMP     Normal_termination        ;  If so, we are all done
  184.  
  185. Return_to_Prior_Dir:
  186.         MOV     DX,OFFSET DotDot_str      ;Point to ".." string (prev dir)
  187.         MOV     AH,3Bh                    ;DOS change dir function
  188.         INT     21h                       ;Change to prior (mother) directory
  189.  
  190.         SUB     [DTA_Ptr],43              ;Go back and re-use prior DTA
  191.         MOV     FF_Flag,Not_first_time    ;Set flag so we do a find next rather
  192.                                           ;   than a find first. (re-use DTA!)
  193.         JMP     Find_Another_SubDirectory ;Keep checking for DIRs
  194.  
  195.         PAGE
  196.         SUBTTL General use subroutines
  197. ;***************************************************************************;
  198. ;**  G e n e r a l    U s e    S u b r o u t i n e s  -    start here     **;
  199. ;***************************************************************************;
  200. ;-----------------------------------------------------------------------------;
  201. ; Get COMSPEC-search the environment for COMSPEC= string (loc of COMMAND.COM) ;
  202. ;-----------------------------------------------------------------------------;
  203. Get_COMSPEC:
  204.         MOV     ES,WORD PTR [Environment] ;Segment address of Environment
  205.         XOR     DI,DI                     ;Start at beginning of segment
  206.         MOV     SI,OFFSET COMPSEC_str     ;Point to "compspec="string
  207.         CLD                               ;Forward direction
  208.         XOR     AX,AX                     ;Constant of zero for comparison
  209. Check_Next_ENV_string:
  210.         CMP     BYTE PTR ES:[DI],0        ;If points to zero, no compspec
  211.         JZ      Missing_COMSPEC           ; FATAL error....
  212.         MOV     DX,DI                     ;Save string pointers
  213.         MOV     BP,SI
  214.         MOV     CX,8                      ;COMSPEC= is 8 characters
  215.         REPZ    CMPSB                     ;Check if we are pointing at comspec=
  216.         MOV     DI,DX                     ;Restore the pointers
  217.         MOV     SI,BP
  218.         JZ      Found_COMSPEC             ;We've got a match
  219.         MOV     CX,200h                   ;Search for a max of 512 bytes
  220.         REPNZ   SCASB                     ;Search for zero byte (AL=0)
  221.         JNZ     Missing_COMSPEC           ; FATAL error....
  222.         JMP     SHORT Check_Next_ENV_string  ;Keep looking for environment strin
  223. Missing_COMSPEC:
  224.         MOV     DX,OFFSET Missing_CS_MSG  ;Message to say comspec= missing
  225.         JMP     Error_Exit
  226. Found_COMSPEC:
  227.         ADD     DI,8                      ;Point to string after COMSPEC=
  228.         MOV     WORD PTR [Command_Adr],DI ;Save address:  offset
  229.         MOV     WORD PTR [Command_Adr+2],ES ;                and SEGMENT too
  230.         RET
  231.  
  232. ;---------------------------------------------------------------;
  233. ; Create EXEC Parm block- setup the parameter block for DOS EXEC;
  234. ;---------------------------------------------------------------;
  235. Create_EXEC_parm_BLOCK:
  236.         MOV     [Parm_Block],ES           ;Environment segment
  237.         MOV     [Parm_Block+4],CS         ;Segment of parameter
  238.         MOV     [Parm_Block+8],CS         ;Segment of FCB #1
  239.         MOV     [Parm_Block+12],CS        ;Segment of FCB #2
  240.         MOV     AX,CS                     ;Point ES back to data segment
  241.         MOV     ES,AX
  242.         RET
  243.  
  244. ;----------------------------------------------------------------------;
  245. ; Create Command tail - setup /C followed by user's program to execute ;
  246. ;    This program is later executed by invokation of COMMAND.COM       ;
  247. ;----------------------------------------------------------------------;
  248. Create_Command_Tail:
  249. ; check program to invoke (parameter at 80h) AKA: PSP parameter
  250.         MOV     AL,PSP_PARM               ;Check # of characters in parameter
  251.         OR      AL,AL                     ;Check if no characters (AL=0)
  252.         JNZ     Parameter_detected        ;  If a parameter passed..
  253.         MOV     DX,OFFSET XALL_Help_MSG   ;If no input,put out syntax msg
  254.         JMP     Error_Exit
  255.  
  256. Parameter_detected:
  257. ; Insert a " /C" in front of the PSP parameter
  258.         ADD     AL,3                      ;Increase length by 3 for " /C"
  259.         MOV     [XALL_Parm],AL            ;Store new character count
  260.         MOV     BYTE PTR[XALL_Parm+1],' ' ;Store blank separator
  261.         MOV     WORD PTR[XALL_Parm+2],'C/';Store /C (after this is actual parm)
  262.         RET
  263.  
  264.  
  265. ;----------------------------------------------------------------------;
  266. ; Display XALL message  - Display name of current directory we are     ;
  267. ;    executing the user's command in.                                  ;
  268. ;----------------------------------------------------------------------;
  269. Display_XALL_MSG:                         ;Display name of current directory
  270.         MOV     DX, offset In_Dir_MSG     ;Begining of "Xing in:" message
  271.         MOV     CX,12                     ;message has 12 chars
  272.         MOV     AH,40h                    ;DOS Write func
  273.         MOV     BX,1                      ;Handle for std output device
  274.         INT     21h                       ;Write Start message
  275. ;  Get the current directory string
  276.         MOV     SI,OFFSET Current_Dir     ;Location to store directory string
  277.         XOR     DX,DX                     ;Default drive
  278.         MOV     AH,47h                    ;DOS Get directory function
  279.         INT     21h
  280. ;   Scan the string in Current_Dir to determine its length:
  281.         MOV     DI,SI                     ;Dir string start
  282.         MOV     DX,SI                     ;Save a copy for use later
  283.         XOR     AX,AX                     ;Scan for zero termination of string
  284.         MOV     CX,64                     ;Scan up to 64 characters
  285.         REPNE   SCASB                     ;Find 1st zero byte
  286.         SUB     DI,DX                     ;Length of directory string
  287.         MOV     CX,DI                     ;Characters to display in dir string
  288. ;DX = start of dir strng, CX = # of chars in string
  289.         MOV     AH,40h                    ;DOS Write func
  290.         INT     21h                       ;Display the actual directory string
  291.         MOV     DX,OFFSET CRLF_str        ;Prepare to put out carriage ret + LF
  292.         MOV     CX,2                      ;Print 2 characters
  293.         MOV     AH,40h                    ;DOS Write func
  294.         INT     21h
  295.         RET
  296.  
  297. ;---------------------------------------------------------------;
  298. ; Error Exit - called with DX pointing to error message to send ;
  299. ;---------------------------------------------------------------;
  300. Error_Exit:
  301.         MOV     AH,09h                    ;DOS display string function
  302.         INT     21h
  303.  
  304.         MOV     DX,OFFSET Hit_Key_Msg     ;Ask user to hit any key
  305.         MOV     AH,09h                    ;DOS display string function
  306.         INT     21H
  307.  
  308. ; Wait for user to hit any key
  309.         XOR     AX,AX
  310.         INT     16h                       ;Wait for user to hit a key
  311.  
  312.         MOV     AX,4C20h                  ;Terminate with 32 errorlevel
  313.         INT     21h                       ;Terminate
  314.  
  315.  
  316. Normal_Termination:
  317. ;                                         ;Terminate with zero (DOS) errorLEVEL
  318.         MOV     AX,4C00h
  319.         INT     21h
  320.  
  321.         SUBTTL  Definition of Data Structures
  322.         PAGE
  323. ;-----------------------------------------------------------------;
  324. ; Data storage definition:                                        ;
  325. ;-----------------------------------------------------------------;
  326. Current_Dir  LABEL  BYTE                  ;Overlay copyright msg with this
  327. XALL_CR_msg  DB 'XALL 1.0 - high speed eXecute ALL subdirectories utility.'
  328.              DB CR,LF
  329.              DB  CR,LF,"MIRDIR 1.0 ",BOX," PCDATA TOOLKIT (c) 1990"
  330.              DB  " Ziff Communications Co.",CR,LF
  331.              DB  "PC Magazine ",BOX," Wolfgang Stiller",CR,LF,"$"
  332. XALL_Help_MSG DB CR,LF,'Syntax is: "XALL anyDOScommand"',CR,LF
  333.              DB '   "anyDOScommand" will then be eXecuted in the current and '
  334.              DB 'all ',CR,LF
  335.              DB '   subordinate subdirectories. The program or batch file to'
  336.              DB ' be executed',CR,Lf
  337.              DB '   must be included in the DOS PATH.$'
  338. Missing_CS_Msg LABEL BYTE                 ;A message starting with comspec strg
  339. COMPSEC_str  DB 'COMSPEC='                ;String in environment to search for
  340.              DB ' missing.',CR,LF,'$'
  341. XALL_Fail_msg DB 'XALL failure.',CR,LF
  342.              DB 'Probably due to bad COMSPEC - no COMMAND.COM.',CR,LF,'$'
  343. EXEC_02_Msg  DB 'Unable to find program.','$'
  344. EXEC_05_Msg  DB 'Program access denied.','$'
  345. EXEC_08_Msg  DB 'Too little free mem.','$'
  346. Hit_Key_Msg  DB CR,LF,LF,'Please hit a key.'
  347. CRLF_Str     DB CR,LF,'$'
  348. In_Dir_MSG   DB CR,LF,'Xing in: \'
  349. COMMAND_Adr  DD 00                        ;Full address COMMAND.COM strng in ENV
  350. Global_str   DB '*.*',0                   ;String for find all files
  351. DotDot_str   DB '..',0                    ;String to return to mother directory
  352.  
  353. Parm_Block   DW 00                        ;Parameter block for DOS EXEC command
  354.              DW XALL_PARM,0
  355.              DW 5Ch,0
  356.              DW 6Ch,0
  357.  
  358. FF_flag      DB 0                         ;First Find flag (=0 means find 1st)
  359. DTA_ptr      DW     DTA_AREA              ;Pointer to a 43 char DTA block
  360. DTA_area     LABEL  BYTE                  ;area of 32 43 byte DTAs
  361. STACK_Bottom EQU    DTA_area+ 32*43       ;Lower limit of the stack
  362. STACK_TOP    EQU    STACK_Bottom + 80h    ;Allocate 128 byte stack
  363. Program_top  EQU    Stack_top+15          ;End of prog + 15 for paragr rounding
  364.  
  365. CSEG         EndS
  366.              END    XALL
  367.